'''
Author: duliang thinktanker@163.com
Date: 2024-06-04 17:18:35
LastEditors: duliang thinktanker@163.com
LastEditTime: 2025-05-31 20:45:51
FilePath: 2024_6_aqdt.py
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
'''

import pyppeteer
import asyncio
import sys
import requests
from pyppeteer.network_manager import Response, Request
from tqdm import tqdm
# from users_lists import *
import json
import requests.cookies
import csv


def pyppeteer_cookies_to_requests_cookies(pyppeteer_cookies):
    """
    将Pyppeteer的Cookie列表转换为requests.cookies.RequestsCookieJar对象
    """
    cookies_jar = requests.cookies.RequestsCookieJar()

    for cookie in pyppeteer_cookies:
        cookies_jar.set(cookie['name'], cookie['value'])
        # httpOnly=cookie['httpOnly'],
        # sameSite=cookie['sameSite'])

    return cookies_jar


# def use_cookies_in_requests(cookies, url, postjson, method='post'):
#     # 将Pyppeteer的Cookies格式转换为requests可用的格式
#     cookie_dict = dict_from_cookiejar(cookies)

#     # 使用requests.Session以维持会话状态
#     s = requests.Session()
#     s.cookies.update(cookie_dict)
#     if method == 'post':
#         s.post(url, headers=headers, data=cookie_dict, json=postjson)
#     else:
#         s.get(url, headers=headers)
#     # 发起带有Cookie的请求
#     response = s.get(url)
#     return response

# 假设你已经有了从Pyppeteer获取的cookies
# 这里直接使用上面获取的cookies作为示例
# use_cookies_in_requests(cookies, 'https://example.com/some_page')


class dati():

    def __init__(self) -> None:
        self.page_agent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36 Edg/125.0.0.0"
        self.headers = {'User-Agent': self.page_agent}
        self.planId = None
        self.paperId = None

    async def intercept_response(self, res: Response):
        # 获取请求的资源类型
        resourceType = res.request.resourceType
        if resourceType in ['xhr']:
            print(res.url)
            if "start" in res.url:
                res_json = await res.json()
                self.paperId = res_json['bean']['id']

    async def toggle_element_visibility(self, page, selector, hide=True):
        """根据hide参数切换元素的可见性：True隐藏，False显示"""
        # 隐藏指定选择器的内容
        script_hide = f'document.querySelector("{selector}").style.display = "none";'
        # 定义一个变量，用于存储显示内容的脚本
        script_show = f'document.querySelector("{selector}").style.display = "";'
        # 判断hide的值，如果为True，则将script_hide赋值给script_to_execute，否则将script_show赋值给script_to_execute
        script_to_execute = script_hide if hide else script_show
        # 异步执行JavaScript代码
        await page.evaluate(script_to_execute)

    async def scroll_to_element(self, page, selector):
        await page.evaluate(
            f'document.querySelector("{selector}").scrollIntoView({{block: "center", behavior: "smooth"}});'
        )

    def load_cookies(self, user_name):
        """尝试加载本地存储的cookie"""
        try:
            with open(f'{user_name}_cookies.json', 'r') as f:
                return requests.cookies.cookiejar_from_dict(json.load(f))
        except (FileNotFoundError, json.JSONDecodeError):
            return None

    def save_cookies(self, user_name, cookies):
        """保存cookie到本地文件"""
        cookie_dict = cookies
        with open(f'{user_name}_cookies.json', 'w') as f:
            json.dump(cookie_dict, f)

    async def run(self, user_name, user_psw):
        if sys.platform == 'win32':
            userDataDir = rf"d:\pyppeteer_tmp\{user_name}_tmp"
            executablePath = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
            # executablePath = r"C:\Program Files (x86)\Microsoft\Edge Beta\Application\msedge.exe"
        else:
            userDataDir = '/home/duliang/Downloads/xx_tmp'
            executablePath = '/usr/bin/google-chrome'
        browser = await pyppeteer.launch({
            'headless':
            False,
            'args': [
                '--window-size=1024,800', '--start-maximized', '--no-sandbox',
                '--disable-infobars'
            ],
            'ignoreDefaultArgs': ['--enable-automation'],
            'dumpio':
            True,
            'userDataDir':
            userDataDir,
            'executablePath':
            executablePath
        })
        page = await browser.newPage()
        # 开启请求拦截
        # await page.setRequestInterception(True)
        # 绑定请求拦截处理器
        page.on(
            'response', lambda response: asyncio.ensure_future(
                self.intercept_response(response)))
        await page.setUserAgent(self.page_agent)
        await page.setViewport({'width': 1024, 'height': 800})
        await page.goto(url="http://www.slaqsczsjs.com/",
                        waitUntil='networkidle2')  #networkidle2
        user_name_input = await page.J(
            'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.panel > uni-view.uni-forms > uni-form > span > uni-view:nth-child(1) > uni-view.uni-forms-item__content > uni-view.uni-easyinput > uni-view > uni-input > div > input'
        )
        user_psw_input = await page.J(
            'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.panel > uni-view.uni-forms > uni-form > span > uni-view:nth-child(2) > uni-view.uni-forms-item__content > uni-view.uni-easyinput > uni-view > uni-input > div > input'
        )
        login_btn = await page.J(
            'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.panel > uni-button'
        )
        await user_name_input.type(str(user_name))
        await user_psw_input.type(str(user_psw))
        await login_btn.click()
        # await page.screenshot({'path': 'example.png'})

        while 1:
            try:
                await page.waitForSelector(
                    'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.mask',
                    state='attached',
                    timeout=100)
                await asyncio.sleep(0.1)
            except asyncio.TimeoutError:
                break
        cookies = await page.cookies()
        cookie_jar = pyppeteer_cookies_to_requests_cookies(cookies)
        # self.save_cookies(user_name, cookies)
        s = requests.Session()
        s.cookies.update(cookie_jar)

        me_resp = s.post('http://www.slaqsczsjs.com/exam/user/me',
                         headers=self.headers)
        if me_resp:
            me_json = me_resp.json()
            if me_json['success']:
                userName = me_json['bean']['userName']
                print(userName, '开始做题')
                id_resp = s.post(
                    url='http://www.slaqsczsjs.com/exam/exam-paper/myList',
                    headers=self.headers,
                    data={
                        'page': 1,
                        'limit': 10,
                    })
                id_json = id_resp.json()
                if id_json:
                    self.planId = id_json['rows'][0]['id']
                    print(self.planId)
                    await page.goto(
                        url=
                        f'http://www.slaqsczsjs.com/#/pages/examTest/examTest?planId={self.planId}',
                        waitUntil='networkidle2')
                    while not self.paperId:
                        await asyncio.sleep(0.1)
                    temp_pagerId = self.paperId
                    self.paperId = None
                    answers_resp = s.post(
                        url='http://www.slaqsczsjs.com/exam/exam-paper/view',
                        headers={
                            **self.headers,
                            **{
                                'Accept-Language':
                                'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
                                'Content-type':
                                'application/x-www-form-urlencoded;charset=UTF-8',
                            }
                        },
                        data={'id': temp_pagerId})
                    answers_json = answers_resp.json()
                    answers_list = []
                    groups = answers_json['bean']['groups']
                    for d in groups:
                        questions = d['questions']
                        for q in questions:
                            answers_list.append(q['question']['stdAnswer'])
                    if answers_list:
                        print(answers_list)
                        # 隐藏元素
                        await page.waitForSelector(
                            'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.fixed-tail > uni-button'
                        )
                        await self.toggle_element_visibility(
                            page,
                            'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.fixed-tail > uni-button',
                            hide=True)

                        for i in range(len(answers_list)):
                            temp_list = list(answers_list[i])
                            if len(temp_list) == 1:
                                print(i + 1, ' 单 ', temp_list[0])
                                option_e = f'#question{i+1} > uni-radio-group > uni-view:nth-child({ord(temp_list[0]) - 64}) > uni-label > uni-radio > div > div'
                                # print(s)
                                await page.waitForSelector(option_e)
                                await self.scroll_to_element(page, option_e)
                                await asyncio.sleep(1)
                                await page.click(option_e)
                                await asyncio.sleep(2)
                            else:
                                print(i + 1, ' 多')
                                for temp in temp_list:
                                    print(temp)
                                    option_e = f'#question{i+1} > uni-checkbox-group > uni-view:nth-child({ord(temp) - 64}) > uni-label > uni-checkbox > div > div'
                                    await page.waitForSelector(option_e)
                                    await self.scroll_to_element(
                                        page, option_e)
                                    await asyncio.sleep(1)
                                    await page.click(option_e)
                                    await asyncio.sleep(1)
                        # # 显示元素
                        await self.toggle_element_visibility(
                            page,
                            'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.fixed-tail > uni-button',
                            hide=False)
                        sumbit_btn = await page.J(
                            'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.fixed-tail > uni-button'
                        )
                        await sumbit_btn.click()
                        confirm_btn = await page.J(
                            'body > uni-app > uni-modal > div.uni-modal > div.uni-modal__ft > div.uni-modal__btn.uni-modal__btn_primary'
                        )
                        await confirm_btn.click()
                        while 1:
                            try:
                                await page.waitForSelector(
                                    'body > uni-app > uni-layout > uni-content > uni-main > uni-page > uni-page-wrapper > uni-page-body > uni-view > uni-view.mask',
                                    state='attached',
                                    timeout=100)
                                await asyncio.sleep(0.1)
                            except asyncio.TimeoutError:
                                break
                        card_resp = s.post(
                            url=
                            'http://www.slaqsczsjs.com/exam/learn-hour-record/have-card',
                            headers=self.headers,
                        )
                        card_json = card_resp.json()
                        if not card_json['success']:
                            print(card_json['msg'])
                            return
                        progress_bar = tqdm(initial=0,
                                            unit='B',
                                            unit_divisor=1024,
                                            unit_scale=True,
                                            desc=f"下载{userName}证书")
                        card_id = card_json['bean']['id']
                        card_download_resp = s.get(
                            url=
                            f'http://www.slaqsczsjs.com/exam/learn-hour-record/download?id={card_id}',
                            headers=self.headers,
                            stream=True)
                        with open(f'./{userName}.pdf', 'wb') as f:
                            for chunk in card_download_resp.iter_content(
                                    chunk_size=512):
                                if chunk:
                                    f.write(chunk)
                                    progress_bar.update(len(chunk))
                        progress_bar.close()
                        print(f'{userName}证书下载完成')
                        await page.waitFor(10000)

        await browser.close()

    async def execute_tasks(self, tasks):
        await asyncio.gather(*tasks)

    def start(self):
        with open('users.csv', 'r', newline='', encoding='utf-8') as f:
            user_list = csv.DictReader(f)
            tasks = [
                self.run(user['account'], user['password'])
                for user in user_list if str(user['status']) != '1'
            ]

            asyncio.run(self.execute_tasks(tasks))


if __name__ == '__main__':
    d = dati()
    d.start()
    # start()
